#include <iostream>
#include <assert.h>
#include <lua5.3/lua.hpp>
#include <unistd.h>

using namespace std;


void cppCallLua()
{
    lua_State* L = luaL_newstate();

    luaL_openlibs(L);

    if(luaL_dofile(L, "./test.lua") != LUA_OK)
    {
        cout << "luaL_dofile  error: " << lua_tostring(L, -1) << endl;
        assert(false);
    }

    lua_getglobal(L, "Sub");
    lua_pushnumber(L, 12);
    lua_pushnumber(L, 10);

    if(lua_pcall(L, 2, 1, 0) != LUA_OK)
    {
        cout << "lua_pcall(L, 2, 1, 0) error : " << lua_tostring(L, -1) << endl;
        assert(false);
    }

    auto result = lua_tonumber(L, -1);
    cout << "result: " << result << endl;
    lua_pop(L, 1);


    lua_getglobal(L, "Add");
    lua_pushnumber(L, 12);
    lua_pushnumber(L, 10);

    if(lua_pcall(L, 2, 1, 0) != LUA_OK)
    {
        cout << "lua_pcall(L, 2, 1, 0) error : " << lua_tostring(L, -1) << endl;
        assert(false);
    }

    auto result1 = lua_tonumber(L, -1);
    cout << "result1: " << result1 << endl;
    lua_pop(L, 1);

    lua_getglobal(L, "fun");
    lua_pushnumber(L, 1);
    lua_pushnumber(L, 2);

    if(lua_pcall(L, 2, 1, 0) != LUA_OK)
    {
        cout << "lua_pcall(L, 2, 1, 0) error : " << lua_tostring(L, -1) << endl;
        assert(false);
    }

    auto result2 = lua_tonumber(L, -1);
    cout << "result2: " << result2 << endl;
    lua_pop(L, 1);


    lua_getglobal(L, "GetString");


    if(lua_pcall(L, 0, 1, 0) != LUA_OK)
    {
        cout << "lua_pcall(L, 0, 1, 0) error : " << lua_tostring(L, -1) << endl;
        assert(false);
    }

    auto result3 = lua_tostring(L, -1);
    cout << "result3: " << result3 << endl;
    lua_pop(L, 1);


    lua_close(L);
}



static int GetString(lua_State* L ) 
{   
    lua_pushstring(L, "hello cpp");
    return 1; // return num
}


static int add(lua_State* L) 
{   
    double num1 = lua_tonumber(L, 1);
    double num2 = lua_tonumber(L, 2);
     
    lua_pushnumber(L, num1 + num2);
    // lua_pushstring(L, "hello cpp");
    return 1; // return num
}


void luaCallCpp()
{
    lua_State* L = luaL_newstate();
    
    luaL_openlibs(L);

    //register function
    lua_register(L, "GetString", GetString);
    lua_register(L, "add", add);
    
    //load file
    if(luaL_dofile(L, "./cpp.lua") != LUA_OK)
    {
        cout << "luaL_dofile error : " << lua_tostring(L, -1) << endl;
        assert(false);
    }
    
    lua_close(L);
}

int main()
{
    // cppCallLua();
    // luaCallCpp();

    while(1)
    {
        luaCallCpp();
        sleep(15);
    }
    return 0;
}